import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class Client {


    private static final String WALLET = "wallet";

    private List<Wallet> walletList;

    private Wallet current;

    private Client() {
    }

    private static final Client instance = new Client();

    public static Client getInstance() {
        return instance;
    }


    private void addWallet(Wallet wallet) {
        this.walletList.add(wallet);
    }

    private static final String CURRENT = "current";

    public List<Wallet> getWalletList() {
        return walletList;
    }

    public void setWalletList(List<Wallet> walletList) {
        this.walletList = walletList;
    }

    public Wallet getCurrent() {
        return current;
    }

    public void setCurrent(Wallet current) {
        this.current = current;
    }

    public boolean addWallet(String dataDir, String name) {

        try {

            File check = new File(dataDir);
            if (!check.exists()) {
                System.out.println("请先新建dataDir");
                return false;
            }

            File file = new File(dataDir, WALLET);
            if (!file.exists()) {
                boolean created = file.mkdirs();
                if (!created) {
                    System.out.println("新建钱包目录失败");
                    return false;
                }
            }

            Wallet wallet = Wallet.createWallet(name + ".txt");
            boolean result = saveWallet(wallet, file);
            if (result) {
                walletList.add(wallet);
                // 如果current为空则将wallet赋值给current
                if (current == null) {
                    current = wallet;
                    Pool.getInstance().setWallet(wallet);
                }
            }
            return result;
        } catch (Exception e) {
            return false;
        }
    }

    public void loadWallet(String dataDir) {

        try {
            File dir = new File(dataDir, WALLET);
            File current = new File(dir, CURRENT);
            if (!current.exists()) {
                if (walletList != null) {
                    this.setCurrent(walletList.get(0));
                }
                return;
            }
            BufferedReader reader = new BufferedReader(new FileReader(current));
            String line = reader.readLine();
            assert line != null;
            File file = new File(dir, line);
            this.setCurrent(loadFrom(file));
        } catch (Exception e) {

        }
    }


    public void loadWallets(String dataDir) {

        List<Wallet> walletList = new ArrayList<>();
        try {
            File file = new File(dataDir, WALLET);
            File[] files = file.listFiles();
            for (File item : files) {
                walletList.add(loadFrom(item));
            }
        } catch (Exception e) {

        }
        this.walletList = walletList;
    }


    private boolean saveWallet(Wallet wallet, File walletDir) {

        File file = new File(walletDir, wallet.getName());
        if (file.exists()) {
            return false;
        }
        try {
            boolean created = file.createNewFile();
            if (created) {

                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                writer.write(wallet.getName());
                writer.newLine();
                writer.write(String.valueOf(wallet.getCreateTime()));
                writer.newLine();
                writer.write(wallet.getPrivateKey());
                writer.newLine();
                writer.write(wallet.getPublicKey());
                writer.newLine();
                writer.write(wallet.getAddress());
                writer.newLine();
                writer.flush();
                return true;
            }

            return false;
        } catch (Exception e) {
            return false;
        }
    }


    public void printCurrent() throws Exception {
        if (current == null) {
            System.out.println("当前钱包为空");
        } else {
            printWallet(current);
        }
    }

    public void printAll() throws Exception {
        for (Wallet wallet : walletList) {
            printWallet(wallet);
        }
    }

    private void printWallet(Wallet wallet) throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("----------------------------");
        System.out.println(wallet.getName());
        System.out.println(simpleDateFormat.format(new Date(wallet.getCreateTime())));
        System.out.println(wallet.getPublicKey());
        System.out.println(wallet.getAddress());
        System.out.println("check===" + Address.checkAddress(wallet.getAddress()));
        System.out.println("----------------------------");
        System.out.println();
    }


    private Wallet loadFrom(File item) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader(item));
        Wallet wallet = new Wallet();
        wallet.setName(reader.readLine());
        wallet.setCreateTime(Long.parseLong(reader.readLine()));
        wallet.setPrivateKey(reader.readLine());
        wallet.setPublicKey(reader.readLine());
        wallet.setAddress(reader.readLine());
        reader.close();
        return wallet;
    }


    boolean pay(String address, int amount, NetWork netWork) throws Exception {
        return current.pay(address, amount, netWork);
    }


    public void extractFromBlock(Block block) {
        List<TransactionId> transactionIdList = block.getTransactionIdList();
        for (TransactionId transactionId : transactionIdList) {
            accept(MemoryDb.getInstance().getTransaction(transactionId));
        }
    }


    public void accept(Transaction transaction) {

        if (transaction == null) {
            return;
        }

        for (Wallet wallet : walletList) {
            if (Arrays.equals(wallet.getPublicKeyByte(), transaction.getPubKey()) && !transaction.isCoinBase()) {
                wallet.addPayLog(transaction.getHash(), transaction);
            }
        }

        List<Cost> costList = transaction.getCosts();
        for (Cost cost : costList) {

            String address = cost.getAddress();

            for (Wallet wallet : walletList) {
                if (address.equals(wallet.getAddress())) {
                    wallet.addToMyReceipt(transaction.getHash(), transaction);
                    break;
                }
            }
        }
    }


    public boolean switchWallet(String name) {

        if (walletList == null) {
            return false;
        }

        for (Wallet wallet : walletList) {
            if (wallet.getName().equals(name + ".txt")) {
                current = wallet;
                return true;
            }
        }

        return false;
    }

}
